package prop;

import java.util.Vector;
import java.util.Vector;

/**
 ** Es la clase para representar los noticias clasificadas en la aplicacion, hereda de la clase Noticia
 * @author Sandra Crespo  
 * 
 */
public class NoticiaClasificada {

    Vector<Tema> llTema;
    Vector<PalabraParaAnadir> llPalabra;
    Vector<PalFrec> pf;
    String titulo;

    /**
     * Crea una noticia clasificada vacia y se inicializan los vectores
     */
    public NoticiaClasificada(String t) {
        /*** {PRE:-}
         * {POST: se crea un tema con el Tema t}
         */
        
        llTema = new Vector<Tema>(0, 1);
        llPalabra = new Vector<PalabraParaAnadir>(0, 1);
        pf = new Vector<PalFrec>(0, 1);
        titulo = t;
    }

    /**
     * Crea una noticia Calsificada con la fecha d, y con el cojunto de palabras y frecuencias vecFrec
     * @param d fecha de la noticia clasificada
     * @param vecFrec es un vector de PalFrec, donde cada PalFrec es una palabra y la frecuencia de la palabra en el documento
     */
    public NoticiaClasificada(Vector<PalFrec> vecFrec, String t) {
        /*** {PRE:vecFrec !=null}
         * {POST: se crea un tema con el titulo t, y se le asocian a la NoticiaClasificada las PalabrasParaAnadir del vector vecFrec}
         */
        
        titulo = t;
        llTema = new Vector<Tema>(0, 1);
        llPalabra = new Vector<PalabraParaAnadir>(0, 1);
        pf = vecFrec;
        for (PalFrec palf : vecFrec) {
            llPalabra.add(palf.p);
        }
    }

    
    /**
     * Consulta los temas asociados a la noticia clasificada
     * @return devuelve un vector de punteros a los temas asociados de la noticia
     */
    public Vector<Tema> getTemas() {
        /*** {PRE:-}
         * {POST:devuelve un Vector de punteros a los Temas de la NoticiaClasificada. El Vector puede estar vacio}*/
        return llTema;
    }

    /**
     * Consulta las palabras asociadas a la noticia clasificada
     * @return devuelve un vector de punteros a las palabras asociadas de la noticia
     */
    public Vector<PalabraParaAnadir> getPalabras() {
        /*** {PRE:-}
         * {POST:devuelve un Vector de punteros a las PalabraParaAnadir de la NoticiaClasificada. El Vector puede estar vacio}*/
        return llPalabra;
    }

    /**
     * Consulta si la noticia esta asociada con un tema cuyo nombre viene dado por el string t
     * @param t nombre del tema que se desea consultar si está asociado o no.
     * @return  booleano que nos indica si existe un tema asociado a noticia cuyo nombre sea el string pasado.
     */
    public boolean esTema(String t) {
        /*** {PRE:-}
         * {POST:true: si hay una Tema asociado a Noticia Clasificada cuyo nombre sea t. false: si no hay ningun Tema asociado a Noticia Clasificada cuyo nombre sea t}*/
        for (Tema tma : llTema) {
            if (t.equals(tma.getNombre())) {
                return true;
            }
        }
        return false;
    }

    /**
     * Consulta si la noticia esta asociada con una palabra cuyo nombre viene dada por el string p
     * @param p nombre de la palabra que se desea consultar si está asociada o no.
     * @return  booleano que nos indica si existe una palabra cuyo nombre sea el string pasado.
     */
    public boolean esPalabra(String p) {
        /*** {PRE:-}
         * {POST:true: si hay una PalabraParaAnadir asociada a Noticia Clasificada cuyo nombre sea p. false: si no hay ninguna PalabraParaAnadir asociada a Noticia Clasificada cuyo nombre sea p}*/
        
        for (PalabraParaAnadir pal : llPalabra) {
            if (p.equals(pal.getValor())) {
                return true;
            }
        }
        return false;
    }

    /**
     * anade un nuevo tema a la noticia clasificada
     * @param t Tema de la noticia que se desea anadir a la noticia
     * @return  booleano que nos indica si el tema se ha anadido bien o no.
     */
    public boolean addTema(Tema t) {
        /*** {PRE:t!=null}
         * {POST:true: si el Tema t se ha anadido correctamente. false: si no se ha anadido correctamente}*/
        return llTema.add(t);
    }

    /**
     * anade una nueva Palabra a la noticia clasificada
     * @param p Palfrec que nos dice la palabra y la frecuencia de la palabra en el documento.
     * @return  booleano que nos indica si la palabra se ha anadido bien o no
     */
    public boolean addPalabra(PalFrec p) {
         /*** {PRE:p!=null}
         * {POST:true: si la PalabraParaAnadir y su frecuencia se han anadido correctamente. false: si no se han anadido correctamente}*/
        
        boolean b1 = llPalabra.add(p.p);
        boolean b2 = pf.add(p);
        return (b1 && b2);
    }

    /**
     * Consulta el numero de palabras asociadas a la noticia
     * @return  entero que nos dice el numero de palabras
     */
    public int sizePalabras() {
       /*** {PRE:-}
         * {POST: devuelve el numero de PalabrasParaAnadir asociadas con la NoticiaClasificada}*/
        return llPalabra.size();
    }

    /**
     * Consulta el numero de temas asociadas a la noticia
     * @return  entero que nos dice el numero de temas
     */
    public int sizeTemas() {
        /*** {PRE:-}
         * {POST: devuelve el numero de Temas asociadas con la NoticiaClasificada}*/
        
        return llTema.size();
    }

    /**
     * operacion que nos defuelve el df, que sirve xa calcular el vector centroide.
     * @return  vector de identificadores y el numero de frecuencias. está normalizado y ordenado por el id de las palabras.
     */
    public Vector<IdFrec> frecuencia(int N) {
         /*** {PRE:-}
         * {POST:true:   vector de identificadores y el numero de frecuencias. está normalizado y ordenado por el id de las palabras.}*/
        
        Vector<IdFrec> dtf = new Vector<IdFrec>(0, 1);
        for (PalFrec palf : pf) {
            if (palf.p.getNApariciones() != 0) {
                IdFrec iF = new IdFrec();
                iF.id = palf.p.getId();
                iF.frec = palf.frec * Math.log10(N / (double) palf.p.getNApariciones());
                dtf.add(iF);
            }
        }
        double aux = Math.sqrt(cuadrados(dtf));
        for (IdFrec idF : dtf) {
            idF.frec = idF.frec * aux;
        }
        quicksort(dtf,0,dtf.size()-1);
        return dtf;
    }

    /**
     * Consulta el titulo de la noticia
     * @return  string que nos dice el titulo de palabras
     */
    public String getTitulo() {
        /*** {PRE:-}
         * {POST:devuelve el titulo de la NoticiaClasificada}*/
        return titulo;
    }
    
    
    
    // ************** OPERACIONES PRIVADAS

    private double cuadrados(Vector<IdFrec> idF) {
        double acum = 0;
        for (IdFrec idf : idF) {
            acum = acum + (idf.frec * idf.frec);
        }
        return acum;
    }

    private void quicksort(Vector<IdFrec> a, int izq, int der) {
        int i = izq;
        int j = der;

        int pivote = a.get((izq + der) / 2).id;
        do {
            while (a.get(i).id < pivote) {
                i++;
            }
            while (a.get(j).id > pivote) {
                j--;
            }
            if (i <= j) {
                swap(a, i, j);
                i++;
                j--;
            }
        } while (i <= j);
        if (izq < j) {
            quicksort(a, izq, j);
        }
        if (i < der) {
            quicksort(a, i, der);
        }
    }

    private void swap(Vector<IdFrec> v, int i, int j) {
//System.out.println("Swapping i = " + i + " j = " + j);
//System.out.println("v before: " + v);
        IdFrec obj = v.elementAt(i);
        v.setElementAt(v.elementAt(j), i);
        v.setElementAt(obj, j);
//System.out.println("v after:  " + v);
    }
}
